Skip to content

Conversation

@sethp
Copy link
Contributor

@sethp sethp commented May 5, 2023

Try it out with:

(cd esp32c3-hal ; cargo run --example sp_monitoring --features direct-boot )

or, to see a spicy-sized heap allocation in action:

(cd esp32c3-hal ; HULK_SMASH='' cargo run --example sp_monitoring --features direct-boot )

Needs to be cleaned up a lot, but this exposes the following interesting details:

  • the debug assist's sp monitoring fires a (synchronous?) interrupt after the sp leaves the monitored range, and
  • functions can allocate arbitrarily large on-stack data-structures, so
  • the handler for that interrupt probably has an invalid stack pointer on entry, thus
  • printing a backtrace via rust code is tricky, since all of that machinery assumes it has, like, a stack to work with.

Also:

  • if interrupts are disabled when the sp moves out of bounds, or the threshold is masked, nothing happens: this has the potential to be extremely funny in (deeply) nested interrupt handlers
  • special care needs to be taken to use the other (maybe non-register-clobbering) features of the debug assist peripheral, which all show up as the same IRQ; maybe comparing sp against _stack at the beginning of _stack_mon_trap?
  • this only links in direct-boot mode (I didn't try mcu-boot); esp-idf doesn't seem to expose (the same) linker symbols for the start/end of the stack

And these possible suggested areas of improvement:

  • it's not super easy to install a vectored interrupt handler to override just a single slot, OR to "reserve" a slot for an interrupt handler that might, say, corrupt some registers and so depend on its handler diverging
    • it would be a fair bit easier (though not easy) if the _vector_table were in ram instead of flash, so I'm pausing here to revisit that change first
  • tracing the "why didn't my interrupt handler work" question is a bit hair-pull-y; the DefaultHandler printing out a message can help, but especially in this context it's hard to know where the CPU's going when it's not printing anything
  • using interrupt slots >Priority::max() is a little funky, even before the complicating factor of needing to use a pseudo-split stack

Relates to: #300

Try it out with:

```
(cd esp32c3-hal ; cargo run --example sp_monitoring --features direct-boot )
```

or, to see a spicy-sized heap allocation in action:

```
(cd esp32c3-hal ; HULK_SMASH='' cargo run --example sp_monitoring --features direct-boot )
```

Needs to be cleaned up a lot, but this exposes the following interesting
details:

* the debug assist's sp monitoring fires a (synchronous?) interrupt
  _after_ the `sp` leaves the monitored range, and
* functions can allocate arbitrarily large on-stack data-structures, so
* the handler for that interrupt probably has an invalid stack pointer
  on entry, thus
* printing a backtrace via rust code is tricky, since all of that
  machinery assumes it has, like, a stack to work with.

Also:

* if interrupts are disabled when the `sp` moves out of bounds, or the
  threshold is masked, nothing happens: this has the potential to be
  extremely funny in (deeply) nested interrupt handlers
* special care needs to be taken to use the other
  (maybe non-register-clobbering) features of the debug assist
  peripheral, which all show up as the same IRQ; maybe comparing sp
  against _stack at the beginning of _stack_mon_trap?
* this only links in direct-boot mode (I didn't try mcu-boot); esp-idf
  doesn't seem to expose (the same) linker symbols for the start/end of
  the stack

And these possible suggested areas of improvement:

* it's not super easy to install a vectored interrupt handler to
  override just a single slot, OR to "reserve" a slot for an interrupt
  handler that might, say, corrupt some registers and so depend on
  its handler diverging
    * it would be a fair bit easier (though not easy) if the
      _vector_table were in ram instead of flash, so I'm pausing here to
      revisit that change first
* tracing the "why didn't my interrupt handler work" question is a bit
  hair-pull-y; the DefaultHandler printing out a message can help, but
  especially in this context it's hard to know where the CPU's going
  when it's not printing anything
* using interrupt slots >Priority::max() is a little funky, even before
  the complicating factor of needing to use a pseudo-split stack

Relates to: esp-rs#300
@jessebraham
Copy link
Member

Thanks for your contribution! Do you have any plans to continue this work, or am I able to close this PR?

@jessebraham
Copy link
Member

Closing this due to inactivity. Please feel free to re-open this PR, or to open a new one, if you wish to return to this work in the future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants